package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatMapper;
import com.jt.pojo.ItemCat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class ItemCatServiceImpl implements ItemCatService{
    @Autowired
    private ItemCatMapper itemCatMapper;
    /**
     * Map<Integer,List<ItemCat>>
     *     0,一级菜单集合
     *     一级Id, 二级菜单集合
     *     二级Id, 三级菜单集合
     *  业务思路:
     *      判断是否已经存在parentId
     *      不存在:  我是第一个元素 封装到list中 之后保存到Map中
     *      存在:    获取List集合,将自己追加到其中
     * @return
     *  扩展知识: map每次都需要查询数据库,如果采用redis缓存,则性能极大的提升 2ms完成查询
     */

    public Map<Integer,List<ItemCat>> getMap(){
        //1.查询全部数据库记录
        List<ItemCat> list = itemCatMapper.selectList(null); //泛型是 <ItemCat> 对象 对象里面封装的属性 不懂可以看 ItemCat类
        //2.将list集合数据，封装到Map集合中
        Map<Integer,List<ItemCat>> map = new HashMap<>();//定义Map集合
        for (ItemCat itemCat:list){  //遍历List集合,拿到对象  数据库中的所有对象
            int parentId = itemCat.getParentId();  //获得ParentId
            if (map.containsKey(parentId)){  //如果Map集合中存在ParentId,就累加  进入同一分类下
                map.get(parentId).add(itemCat); //通过map.get(parentId) 获得相对应的List集合  然后累加对象进入.add(itemCat)
            }else {                            //如果没有对应的ParentId 则需要新建相对应的List集合
                ArrayList<ItemCat> temp = new ArrayList<>();//新建List集合  用来存放同一级的对象
                temp.add(itemCat);          //存入第一个对象
                map.put(parentId,temp);     //把List集合放入Map集合
            }
        }
        return map;  //返回集合,此时Map集合就是数据表
    }

    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        Map<Integer,List<ItemCat>> map = getMap();  //调用上面的方法获取Map集合,就是获取数据表的所有信息
        if (level == 1){  //如果是一级
            return map.get(0);  //获取ParentId = 0 的所有对象
        }
        if (level == 2){  //如果是二级
            return getTowList(map); //调用下面方法获取 , 传入参数map
        }
        return getThreeList(map);  //最后一种可能 , 运行方法,传入参数map
    }


    private List<ItemCat> getTowList(Map<Integer, List<ItemCat>> map) {
        //1.获取一级菜单
        List<ItemCat> oneList = map.get(0);
        //2.遍历数据
        for (ItemCat oneItemCat:oneList) { //获取一级对象
            //key
            int parentId = oneItemCat.getId();  //获取一级对象的ID 作为子类二级对象的 parentId
            //根据父级查询子集
            List<ItemCat> twoList = map.get(parentId); //根据父类的ID获取子集集合
            //封装子集数据
            oneItemCat.setChildren(twoList); //将子集集合作为属性封装进父级对象,  也是在标识父子关系
        }
        return oneList;  //返回一级对象
    }

    private List<ItemCat> getThreeList(Map<Integer, List<ItemCat>> map) {
        //1.获取一级和二级
        List<ItemCat> oneList = getTowList(map);//一级数据不可能为null  调用上面方法获取一级对象  与 一级对象属性中封装的二级对象
        //2.遍历集合 获取二级的数据
        for (ItemCat oneItemCat:oneList){       //遍历一级对象集合获取一级对象
            //二级数据有可能为null
            List<ItemCat> twoList = oneItemCat.getChildren(); //获取一级对象中封装的二级对象  就是一级对象的属性 Children
            if (twoList == null || twoList.size() == 0){  //查看二级对象是否为空  twoList.size() == 0 判断集合是否有元素 与 .isEmpty()相同
                //表示数据没有二级 本次循环应该终止，开始下一次循环                     twoList == null 表示有没有为其赋予地址值 判断有没有对list集合分配内存空间
                continue;  //跳出本次循环,进入下一次循环  再次判断下一个 一级对象中 Children属性 是否为空
            }
            //二级列表一定有值,可以查询三级列表
            for (ItemCat twoItemCat : twoList){  //二级列表有值 遍历二级集合 获取二级对象
                //获取二级Id.查询三级数据
                int parentId = twoItemCat.getId();  //获取二级对象的ID 作为子类三级对象的 parentId
                List<ItemCat> threeList = map.get(parentId); //根据父类的ID获取子集集合 三级对象集合
                //将三级保存到二级数据中
                twoItemCat.setChildren(threeList);  //将子集集合作为属性封装进父级对象,  也是在标识父子关系
            }

        }
        return oneList;  //返回一级对象   一级包含二级  二级包含三级  一级的 Children属性是封装的二级  二级的 Children属性是封装的三级
    }

//    @Override
//    public List<ItemCat> findItemCatList(Integer level) {
//        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("parent_id", 0);
//        //查询一级
//        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//        for (ItemCat oneItemCat:oneList) {
//            //清空历史条件
//            queryWrapper.clear();
//            queryWrapper.eq("parent_id", oneItemCat.getId());
//            //查询二级数据
//            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
//            for (ItemCat twoItemCat:twoList) {
//                //清空历史条件
//                queryWrapper.clear();
//                queryWrapper.eq("parent_id", oneItemCat.getId());
//                //查询三级数据
//                List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
//                twoItemCat.setChildren(threeList);
//            }
//            oneItemCat.setChildren(twoList);
//        }
//        return oneList;
//    }

    @Override
    @Transactional
    public void UpdatestatusId(ItemCat itemCat) {
        itemCat.setUpdated(new Date());
        itemCatMapper.updateById(itemCat);
    }

    @Override
    @Transactional
    public void saveItemCat(ItemCat itemCat) {
        itemCat.setStatus(true);
        itemCatMapper.insert(itemCat);
    }

    @Override
    @Transactional
    public void updateItemCat(ItemCat itemCat) {
        itemCatMapper.updateById(itemCat);
    }


    /**
     * 要求: 高效的删除
     * 策略:
     *      1.如果level=3 则可以直接删除
     *      2.如果level=2  先查询是否有3级, 如果有直接删除,没有只删除2级
     *      3.如果level=1  先查询2级,再查询3级. 先删除3级,再删除2级,再删除一级
     * @param itemCat
     */
    @Override
    @Transactional
    public void deleteItemCat(ItemCat itemCat) {
        //1.删除3级
        if (itemCat.getLevel() == 3){
            itemCatMapper.deleteById(itemCat.getId());
        }
        //2.删除2级
        //SQL语句: sql where parent_id=xx or id=xx
        if (itemCat.getLevel() == 2){
            int parentId = itemCat.getId();
            QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id",parentId)
                        .or()
                        .eq("id",itemCat.getId());
            itemCatMapper.delete(queryWrapper);
        }
        //3.删除1级  核心是二级菜单
        if (itemCat.getLevel() == 1){
            int oneId = itemCat.getId();
            QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id",oneId);
            //获取二级ID
            List<Object> twoIds = itemCatMapper.selectObjs(queryWrapper);
            //通过二级ID 删除三级数据
            //where parent_id in twoIds or id in twoIds or id = oneId
            queryWrapper.clear(); //清除缓存
            queryWrapper.in(twoIds != null && twoIds.size() > 0 ,"parent_id",twoIds)
                        .or( )
                        .in(twoIds != null && twoIds.size() > 0 ,"id",twoIds)
                        .or()
                        .eq("id",oneId);
            itemCatMapper.delete(queryWrapper);
        }
    }


}
